<template>
  <div class="px-4 py-2 flex flex-col gap-y-2">
    <div class="flex items-center justify-between">
      <span class="textlabel">
        {{ title }}
      </span>

      <div v-if="!isCreating && allowEdit" class="flex items-center gap-x-2">
        <NButton v-if="!state.isEditing" size="tiny" @click.prevent="beginEdit">
          {{ $t("common.edit") }}
        </NButton>
        <NButton
          v-if="state.isEditing"
          size="tiny"
          :disabled="state.description === plan.description"
          :loading="state.isUpdating"
          @click.prevent="saveEdit"
        >
          {{ $t("common.save") }}
        </NButton>
        <NButton
          v-if="state.isEditing"
          size="tiny"
          quaternary
          @click.prevent="cancelEdit"
        >
          {{ $t("common.cancel") }}
        </NButton>
      </div>
    </div>

    <div class="text-sm">
      <NInput
        v-if="isCreating || state.isEditing"
        ref="inputRef"
        v-model:value="state.description"
        :placeholder="$t('issue.add-some-description')"
        :autosize="{ minRows: 3, maxRows: 10 }"
        :disabled="state.isUpdating"
        :loading="state.isUpdating"
        style="
          width: 100%;
          --n-placeholder-color: rgb(var(--color-control-placeholder));
        "
        type="textarea"
        size="small"
        @update:value="onDescriptionChange"
      />
      <div
        v-else
        class="min-h-[3rem] max-h-[12rem] whitespace-pre-wrap px-[10px] py-[4.5px] text-sm"
      >
        <template v-if="plan.description">
          <iframe
            v-if="plan.description"
            ref="contentPreviewArea"
            :srcdoc="renderedContent"
            class="rounded-md w-full overflow-hidden"
          />
        </template>
        <span v-else class="text-control-placeholder">
          {{ $t("issue.add-some-description") }}
        </span>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { NInput, NButton } from "naive-ui";
import { computed, nextTick, reactive, ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import { useRenderMarkdown } from "@/components/MarkdownEditor";
import { planServiceClient } from "@/grpcweb";
import { pushNotification, useCurrentUserV1 } from "@/store";
import { Plan } from "@/types/proto/v1/plan_service";
import { extractUserResourceName, hasProjectPermissionV2 } from "@/utils";
import { usePlanContext } from "../../logic";

type LocalState = {
  isEditing: boolean;
  isUpdating: boolean;
  description: string;
};

const { t } = useI18n();
const { isCreating, plan } = usePlanContext();
const currentUser = useCurrentUserV1();
const contentPreviewArea = ref<HTMLIFrameElement>();

const state = reactive<LocalState>({
  isEditing: false,
  isUpdating: false,
  description: plan.value.description,
});

const inputRef = ref<InstanceType<typeof NInput>>();

const title = computed(() => {
  return t("common.description");
});

const allowEdit = computed(() => {
  if (isCreating.value) {
    return true;
  }

  if (extractUserResourceName(plan.value.creator) === currentUser.value.email) {
    // Allowed if current user is the creator.
    return true;
  }

  if (hasProjectPermissionV2(plan.value.projectEntity, "bb.plans.update")) {
    // Allowed if current has plan update permission in the project
    return true;
  }
  return false;
});

const onDescriptionChange = (description: string) => {
  if (isCreating.value) {
    plan.value.description = description;
  }
};

const beginEdit = () => {
  state.description = plan.value.description;
  state.isEditing = true;
  nextTick(() => {
    inputRef.value?.focus();
  });
};

const saveEdit = async () => {
  try {
    state.isUpdating = true;
    const planPatch = Plan.fromJSON({
      ...plan.value,
      description: state.description,
    });
    const updated = await planServiceClient.updatePlan({
      plan: planPatch,
      updateMask: ["description"],
    });
    Object.assign(plan.value, updated);
    pushNotification({
      module: "bytebase",
      style: "SUCCESS",
      title: t("common.updated"),
    });
    state.isEditing = false;
  } finally {
    state.isUpdating = false;
  }
};

const cancelEdit = () => {
  state.description = plan.value.description;
  state.isEditing = false;
};

const { renderedContent } = useRenderMarkdown(
  computed(() => plan.value.description),
  contentPreviewArea,
  computed(() => plan.value.projectEntity)
);

// Reset the edit state after creating the plan.
watch(isCreating, (curr, prev) => {
  if (!curr && prev) {
    state.isEditing = false;
  }
});

watch(
  () => plan.value,
  (plan) => {
    if (state.isEditing) return;
    state.description = plan.description;
  },
  { immediate: true }
);
</script>
